package controller;

import model.Point;

import java.io.File;
import java.util.Random;



import Tools.UtilFactory;
import model.ASserver;
import model.ASuserInfo;
import model.EC;
import model.OBU;

/**
 * 核心操作类，实现系统的各种功能
 * @author BINGBING
 *
 */
public class operator {
	    //xml对象的保存路径
		static String path="D://TEAM//ObjectXml/";
	
	//用户登录方法
	public static int login(String ID,String pwd){
		System.out.println("用户ID为:"+ID+"的用户请求登陆");
		int result=0;
		String B="null";
		String C="null";
		ASuserInfo info=new ASuserInfo();
		OBU obu=new OBU();
		try{
			String filepath=path+ID+"Userinfo.xml";
			File userinfo=new File(filepath);
			if (!userinfo.exists()){
				//说明该用户不存在，提示用户注册
				throw new RuntimeException("用户不存在，请注册！");
			}
		    info=(ASuserInfo) UtilFactory.objectXmlDecoder(filepath).get(0);
			B=info.getB();
			C=info.getC();
			if (B.equals("null")||C.equals("null")){
				//说明该用户未注册
				throw new RuntimeException("该用户未注册");
			}
			System.out.println("该用户存在，且获取到改用户的B值为:"+B);
			System.out.println("该用户存在，且获取到改用户的C值为:"+C);
			/**
			 * hash函数选取为HASH-512
			 * 将hash（pwd）异或C的值与B的值进行比对，如果相等则通过验证
			 */
			String Bget=UtilFactory.HexXor(UtilFactory.SHA512(pwd), C);
			System.out.println("用户密码的hash值与C值进行异或得到的B值为:"+Bget);
			if (!Bget.equals(B)) throw new RuntimeException("用户名或密码错误");
			result=1;
			System.out.println("计算得到的B值与该用户注册时生成的B值匹配，登陆成功");
		} catch (Exception e) {
			System.err.println("登录过程异常:"+e.getMessage());
		}
		return result;
	}
	
	//用户注册方法
	public static int signIn(String ID,String pwd){
		System.out.println("用户ID为:"+ID+"的用户进入注册");
		int returnres=0;
		//服务商需要先获取自己私钥和当前有效的psk
		String ASID="0000000000";
		String pubkeyx="null";
		String pubkeyy="null";
		String prikey="null";
		String hash="null";
		String P="null";
		String px="null";
		String py="null";
		//8f4fb76a0ed98c98b7e123dbe34549bacbbb4f6b9ab1e477e39988a9c34e8e3ee6a31a4dbde3f15c5c5ae5e484dbf23f4ddd55ff9d01e49607567fd206e278fb
		String psk="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011";
		ASserver as=new ASserver();
		as.setEca("1");
		as.setEcb("1");
		as.setEcp("23");
		as.setEcpx("1");
		as.setEcpy("1");
		as.setPrivatekey("7");
		as.setPubkeyx("7");
		as.setPublickeyy("2");
		
		try {
			//获取当前AS服务商
//			List<ASserver>servers=UtilFactory.objectXmlDecoder("ObjectXml/0000000000.xml");
//			as=servers.get(0);
//			if (as==null){
//				throw new RuntimeException("AS服务商信息获取异常");
//			}
			pubkeyx=as.getPubkeyx();
			pubkeyy=as.getPublickeyy();
			prikey=as.getPrivatekey();
			P=as.getEcp();
			px=as.getEcpx();
			py=as.getEcpy();
			System.out.println("AS服务商公钥的X坐标为:"+pubkeyx);
			System.out.println("AS服务商公钥的Y坐标为:"+pubkeyy);
			System.out.println("AS服务商私钥为:"+prikey);
			System.out.println("AS服务商生成椭圆曲线的P为:"+P);
			System.out.println("AS服务商生成椭圆曲线的生成元的X坐标为:"+px);
			System.out.println("AS服务商生成椭圆曲线的生成元的Y坐标为:"+py);
			//已经获得正确的AS的私钥privateKey和当前有效的psk
			/**
			 * 将ID与私钥privatekey连接起来进行一次hash运算得到A
			 * 对得到的A进行一次hash运算得到B
			 * 将pwd进行一次hash运算之后得到的值与B进行异或运算得到C
			 * 将psk与A进行异或运算得到D
			 */
			System.out.println("AS服务商获取到当前有效的PSK为:"+psk);
			String A=UtilFactory.SHA512(ID+prikey);
			String B=UtilFactory.SHA512(A);
			String C=UtilFactory.HexXor(UtilFactory.SHA512(pwd), B);
			String D=UtilFactory.HexXor(psk, A);
			System.out.println("计算得到用户ID为:"+ID+"的A值为"+A);
			System.out.println("计算得到用户ID为:"+ID+"的B值为"+B);
			System.out.println("计算得到用户ID为:"+ID+"的C值为"+C);
			System.out.println("计算得到用户ID为:"+ID+"的D值为"+D);
			/**
			 * 注册成功，将生成的B,C,D,使用的hash函数，椭圆曲线模数p
			 * 椭圆曲线生成元P（x,y）,公钥发送给用户，即写入OBU维护的表中
			 */
			try {
				OBU obu=new OBU();
				ASuserInfo userinfo=new ASuserInfo();
				userinfo.setA(A);
				userinfo.setAsid(as.getAsid());
				userinfo.setB(B);
				userinfo.setC(C);
				userinfo.setId(ID);
				userinfo.setD(D);
				String infopath=path+userinfo.getId()+"Userinfo.xml";
				UtilFactory.objectXmlEncoder(userinfo, infopath);
				
				obu.setAsp(P);
				obu.setAspublickeyx(pubkeyx);
				obu.setAspublickeyy(pubkeyy);
				obu.setAspx(px);
				obu.setAspy(py);
				obu.setObub(B);
				obu.setObuc(C);
				obu.setObud(D);
				obu.setObuhash(as.getHash());
				obu.setObuid(ID);
				String obupath=path+ID+".xml";
				UtilFactory.objectXmlEncoder(obu, obupath);
			} catch (Exception e) {
				throw new RuntimeException("同时更新OBU和ASuserInfo表事务失败。。。");
			}
			//注册成功，设置成功返回状态为1
			System.out.println("用户ID为:"+ID+"的用户注册成功");
			returnres=1;
		} catch (Exception e) {
		System.out.println("注册用户异常:"+e.getMessage());
		}
		return returnres;
	}
	
	//用户向LE请求认证,返回当前有效的psk
	public static String getCheck(String ID){
		System.out.println("用户ID为:"+ID+"的用户向LE请求认证");
		String returnvalue="null";
		/**
		 * 1、用户端获取该车辆维护的信息OBU
		 * 2、随机产生一个随机数N1
		 * 3、将B的hash值与随机数N1进行异或得到M1
		 * 4、将N1的hash值与登陆ID异或得到AID
		 * 5、将N1、AID、D进行字符串连接再计算出hash值得到M2
		 */
		//1、用户端获取该车辆维护的信息OBU
		OBU obu=new OBU();//注意这里不能写成null，否则会造成异常
		try {
			String obupath=path+ID+".xml";
			File obufile=new File(obupath);
			if (!obufile.exists()){
				throw new RuntimeException("该用户没有注册，结束认证");
			}
			obu=(OBU) UtilFactory.objectXmlDecoder(obupath).get(0);
			//2、产生随机数N1
			//int N1=new Random(1000).nextInt();
			System.out.println("用户开始生成请求认证的信息:");
			String N1=""+new Random().nextInt(10);
			System.out.println("用户端产生的随机N1的值="+""+N1);
			//3、将B的hash值与随机数N1进行异或得到M1
			String M1=UtilFactory.HexXor(UtilFactory.SHA512(obu.getObub()),""+N1);
			System.out.println("用户端生成的M1值为:"+M1);
			//4、将N1的hash值与登陆ID异或得到AID
			String AID=UtilFactory.HexXor(UtilFactory.SHA512(""+N1), ID);
			System.out.println("用户端生成的AID信息为:"+AID);
			//5、将N1、AID、D进行字符串连接再计算出hash值得到M2
			String M2=UtilFactory.SHA512(N1+AID+obu.getObud());
			System.out.println("用户端生成的M2信息为:"+M2);
			/**
			 * LE认证过程
			 * 1、获取当前有效的psk
			 * 2、将当前有效的psk与接收到的待验证用户的D进行异或得到A
			 * 3、将接收到的M1与对A进行两次hash运算得到的值进行异或得到N1
			 * 4、将N1与接收到的AID、D连接后进行hash运算得到的值与M2进行对比，正常情况下是相等的
			 * 5、将接收到的AID与N1的hash值进行异或得到用户ID
			 * 6、产生一个随机数N2
			 * 6.1、将LE的IDj与N2进行异或得到AIDj
			 * 7、将N1与N2连接计算hash值得到SKij
			 * 8、将N2与N1两次hash的值进行异或得到M3
			 * 9、将接收到的A与IDj的hash值进行异或得到M4
			 * 10、将M4、N2、AIDj连接的值进行hash运算得到M5
			 * 11、将AIDj、M3、M4、M5发送给用户
			 */
			System.out.println("LE接收到请求认证的用户发送过来的认证消息，开始进行处理:");
			//LE接收到的M1，M2，D，AID信息
			String D=obu.getObud();
			String IDj="ffff";//假设一个LE的ID号
			System.out.println("假定当前接收认证的LE的ID为:"+IDj);
			//声明待发送的信息
			String AIDj="null",M3="null",M4="null",M5="null",SKij="null";
			//1、获取当前有效的psk
			String psk="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011";
			System.out.println("LE获取到该用户注册时AS服务商使用的PSK值为:"+psk);
			//2、将当前有效的psk与接收到的待验证用户的D进行异或得到A
			String A=UtilFactory.HexXor(D, psk);
			System.out.println("LE计算出当前请求认证车辆的A值为:"+A);
			// 3、将接收到的M1与对A进行两次hash运算得到的值进行异或得到N1
			String N1get=UtilFactory.HexXor(M1, UtilFactory.SHA512(UtilFactory.SHA512(A)));
			N1get=N1get.substring(N1get.lastIndexOf("0")+1, N1get.length());
			System.out.println("LE计算出用户得到请求认证消息时使用的随机数N1为:"+N1get);
			// 4、将N1与接收到的AID、D连接后进行hash运算得到的值与M2进行对比，正常情况下是相等的
			String M2get=UtilFactory.SHA512(N1get+AID+D);
			System.out.println("LE经过计算得到的M2值为:"+M2get);
			if (M2get.equals(M2)){
				System.out.println("M2是匹配的。。。。。。");
			}
			else{
				throw new RuntimeException("M2信息不匹配，结束认证");
			}
			//5、将接收到的AID与N1的hash值进行异或得到用户ID
			String IDget=UtilFactory.HexXor(AID, UtilFactory.SHA512(""+N1));
			IDget=IDget.substring(IDget.lastIndexOf("0")+1, IDget.length());
			System.out.println("LE经过计算得到认证车辆的ID为:"+IDget);
			//6、产生一个随机数N2
			//String N2=""+new Random(1000).nextInt();
			String N2=""+new Random().nextInt(10);
			System.out.println("LE端产生的随机数为:"+N2);
			//7、将LE的IDj与N2进行异或得到AIDj
			AIDj=UtilFactory.HexXor(IDj, N2);
			System.out.println("LE端产生的AIDj为:"+AIDj);
			//8、将N1与N2连接计算hash值得到SKij
			SKij=UtilFactory.SHA512(N1get+N2);
			System.out.println("LE端产生的SKij为:"+SKij);
			//9、将N2与N1两次hash的值进行异或得到M3
			M3=UtilFactory.HexXor(N2, UtilFactory.SHA512(UtilFactory.SHA512(N1get)));
			System.out.println("LE端产生的M3值为:"+M3);
			//10、将接收到的A与IDi的hash值进行异或得到M4
			M4=UtilFactory.HexXor(A, UtilFactory.SHA512(IDget));
			System.out.println("LE端产生的M4值为:"+M4);
			// 11、将M4、N2、AIDj连接的值进行hash运算得到M5
			M5=UtilFactory.SHA512(M4+N2+AIDj);
			System.out.println("LE端产生的M5值为:"+M5);
			System.out.println("LE将产生的信息发送给请求认证的车辆");
			//12、将AIDj、M3、M4、M5发送给用户
			
				/**
				 * 验证的用户接收到LE发来的AIDj、M3、M4、M5信息进行处理
				 * 1、将M3与N1的两次hash值进行异或得到N2
				 * 2、将AIDj、M4、N2连接进行hash运算得到的值与M5进行对比，正常情况下是相等的
				 * 3、将自己的ID进行hash运算得到的值与M4进行异或得到Ai
				 * 4、将N1与N2连接进行hash运算得到SKij
				 * 5、如果身份合法，将计算得到的Ai与Di进行异或可以得到当前有效的psk
				 * 6、将SKij与N2的hash值进行异或后发给LE，告知验证成功
				 */
			System.out.println("请求认证的车辆接收到LE发送过来的信息，开始进行处理");
			String pskUser="null";
			//1、将M3与N1的两次hash值进行异或得到N2
			String N2get=UtilFactory.HexXor(M3, UtilFactory.SHA512(UtilFactory.SHA512(N1)));
			N2get=N2get.substring(N2get.lastIndexOf("0")+1);
			System.out.println("用户端计算出来的N2值为:"+N2get);
			//2、将AIDj、M4、N2连接进行hash运算得到的值与M5进行对比，正常情况下是相等的
			String M5get=UtilFactory.SHA512(M4+N2get+AIDj);
			System.out.println("用户端计算得到的M5的值为:"+M5get);
			if (M5get.equals(M5)){
				System.out.println("M5是匹配的");
			}
			else{
				throw new RuntimeException("M5信息不匹配，认证结束");
			}
			//3、将自己的ID进行hash运算得到的值与M4进行异或得到Ai
			String Ai=UtilFactory.HexXor(UtilFactory.SHA512(ID), M4);
			System.out.println("用户端计算得到的A值为:"+Ai);
			//4、将N1与N2连接进行hash运算得到SKij
			String SKijget=UtilFactory.SHA512(N1+N2get);
			System.out.println("用户端计算得到的SKij的值为:"+SKijget);
			//5、如果身份合法，将计算得到的Ai与Di进行异或可以得到当前有效的psk
			pskUser=UtilFactory.HexXor(Ai, obu.getObud());
			//6、将SKij与N2的hash值进行异或后发给LE，告知验证成功
			String message=UtilFactory.HexXor(SKijget, UtilFactory.SHA512(N2get));
			System.out.println("用户端获得的有效psk为"+pskUser);
			System.out.println("用户端获取到PSK，告知LE的信息为:"+message);
			System.out.println("用户获取到当前有效的PSK，成为合法车辆，告知LE");
			/**
			 * LE接收用户发送来的信息，验证状态
			 * 1、将N2的hash值与接收用户的值进行对比，相等则用户已经获得psk
			 */
			
			//1、将N2的hash值与接收用户的值进行对比，相等则用户已经获得psk
			System.out.println("LE接收到认证用户的告知信息");
			if(message.equals(UtilFactory.HexXor(SKij, UtilFactory.SHA512(N2)))){
				System.out.println("LE接收到用户端发送的告知信息，确认用户已获得当前有效的PSK");
				//激活成功，将当前有效的psk写入到认证用户的OBU表中
				obu.setObupsk(pskUser);
				UtilFactory.objectXmlEncoder(obu, obupath);
			}else{
				System.out.println("LE接收到用户端发送的告知信息，信息不匹配，无法确认用户是否已获得当前有效的PSK");
			}
			returnvalue=pskUser;
		} catch (Exception e) {
			System.err.println("获取OBU信息异常"+e.getMessage());
		}
		return returnvalue;
	}
	
	//用户修改密码
	public static int fixPassword(String ID,String oldpwd,String newpwd){
		/**
		 * 1、获得该用户的B、C以及系统采用的hash算法
		 * 2、用oldpwd的hash值与C进行异或得到的值与B对比是否相等，相等则当前操作用户为用户本身（知道密码的用户）
		 * 3、将C、oldpwd的hash值、newpwd的hash值两两进行异或得到新的Cnew
		 * 4、更新服务商处存储的用户信息以及用户端自己维护的OBU中的信息
		 */
		System.out.println("ID为:"+ID+"的车辆请求修改密码");
		int returnvalue=0;
		String Cnew="";
		String B="null";
		String C="null";
		ASuserInfo info=new ASuserInfo();
		OBU obu=new OBU();
		try {
			String obupath=path+ID+".xml";
			String filepath=path+ID+"Userinfo.xml";
			File userinfo=new File(filepath);
			File obufile=new File(obupath);
			if (!userinfo.exists()||!obufile.exists()){
				//说明该用户不存在，提示用户注册
				throw new RuntimeException("用户不存在，请注册！");
			}
			info=(ASuserInfo) UtilFactory.objectXmlDecoder(filepath).get(0);
			obu=(OBU) UtilFactory.objectXmlDecoder(obupath).get(0);
			B=info.getB();
			C=info.getC();
			//1、获得该用户的B、C以及系统采用的hash算法
			if (B.equals("null")||C.equals("null")){
				//用户登录成功了才能进行修改密码的操作，如果获取不到信息，则说明服务器端出现了问题
				throw new RuntimeException("服务器异常。。。。");
			}
			System.out.println("获取到该用户的B值为:"+B);
			System.out.println("获取到该用户的C值为:"+C);
			//2、用oldpwd的hash值与C进行异或得到的值与B对比是否相等，相等则当前操作用户为用户本身（知道密码的用户）
			String Bget=UtilFactory.HexXor(UtilFactory.SHA512(oldpwd), C);
			System.out.println("使用用户密码和C值进行异或得到的B值为:"+Bget);
			if (!Bget.equals(B)){
				throw new RuntimeException("用户身份不匹配");
			}
			System.out.println("根据用户提供的新密码计算新的C值");
			//3、将C、oldpwd的hash值、newpwd的hash值两两进行异或得到新的Cnew
			Cnew=UtilFactory.HexXor(UtilFactory.HexXor(C, UtilFactory.SHA512(oldpwd)), UtilFactory.SHA512(newpwd));
			System.out.println("计算得到新的C值为:"+Cnew);
			System.out.println("更新服务器端和用户端C值");
			//4、更新服务商处存储的用户信息以及用户端自己维护的OBU中的信息，此处要进行事务管理
			try {
				info.setC(Cnew);
				obu.setObuc(Cnew);
				//取消数据库事务的自动提交功能，进行手动管理
				//更新服务商处存储的用户信息
				UtilFactory.objectXmlEncoder(info, filepath);
				//更新用户端自己维护的信息OBU
				UtilFactory.objectXmlEncoder(obu, obupath);
				System.out.println("用户修改密码成功");
				returnvalue=1;
			}catch (Exception e) {
				throw new RuntimeException("更新C信息失败");
			}
			
		} catch (Exception e) {
			System.out.println("修改密码异常"+e.getMessage());
		}
		return returnvalue;
	}
	
	//两车实现通信前的身份验证,toID表示要进行通信车辆的ID，认证成功返回实现安全通信的秘钥
	public static String safeCommunicate(String fromID,String toID){
		System.out.println("ID为:"+fromID+"的车辆向ID为:"+toID+"的车辆请求通信");
		String communicationKey="null";
		EC ec=new EC();
		ASserver as=new ASserver();
		as.setEca("1");
		as.setEcb("1");
		as.setEcp("23");
		as.setEcpx("1");
		as.setEcpy("1");
		as.setPrivatekey("7");
		as.setPubkeyx("7");
		as.setPublickeyy("2");
		//假定从用户端存储的信息中能够获取到服务商使用的椭圆曲线
		String aspath=path+"0000000000.xml";
		OBU obu1=new OBU();
		String obu1path=path+fromID+".xml";
		OBU obu2=new OBU();
		String obu2path=path+toID+".xml";
		
		/**
		 * 注：所有的点进行hash运算，是将横坐标和纵坐标连接起来再进行异或
		 * 两车之间实行安全通信，确认安全之后通过双方共同知道的秘钥k进行安全通信
		 * 注：所有对点进行字符串连接的均用x坐标
		 * 1、USER1获取自己的ID1、AS的公钥publickey1、生成元P（x1,y1），通过认证获得的当前有效的psk1
		 * 2、产生一个随机数r1
		 * 3 将r1与publickey1乘积的hash值与ID1进行异或得到AID1
		 * 4、将r1与P（x1，y1）相乘得到点T(Tx1,Ty1)
		 * 5、将psk1与P（x1,y1）相乘得到的点+T得到点u1(u1x1,u1y1)
		 * 6、将T1、u1、AID1的连接进行hash运算得到M1
		 * USER1将AID1，u1,M1发送给USER2
		 * 7、USER2获取自己的ID2、AS的公钥publickey2、生成元P（x2,y2）,通过认证获得的当前有效的psk2（当前所有用户为同一个值）
		 * 8、将u1-psk2与P（x2,y2）相乘的值得到新的点T2(Tx2,Ty2)
		 * 9、将T2、u1、AID1的连接进行hash运算得到值与M1对比，相同则继续通信，否则结束通信
		 * 10、产生一个随机数r2，将r2与publickey2相乘再进行hash运算的值与ID2进行异或运算得到AID2
		 * 11、r2与P（x2,y2）相乘得到新的点R（Rx，Ry）
		 * 12、将psk2*P（x2，y2）的值加上R（Rx，Ry）得到新的点u2
		 * 13、将r2*T2(Tx2,Ty2)得到新的点S（Sx,Sy）
		 * 14、将T2、R、S进行连接再进行hash运算得到K
		 * 15、将AID2与K进行连接再计算hash值得到M2
		 * USER2将AID2，u2,M2发送给USER1
		 * 16、u2-publickey1*P(x1,y1)得到R1
		 * 17、r1*R1得到S1
		 * 18、计算k1=hash(T||R1||s1)
		 * 19、验证M2？=hash(AID1||k1)
		 * 20、计算M3=hash(u2||k1)
		 * USER1将M3发送给USER2
		 * 21、验证M3？=hash(u2||K)
		 */
		try {
			//得到服务商的信息
			//as=(ASserver) UtilFactory.objectXmlDecoder("ObjectXml/0000000000.xml").get(0);
			ec.a=Integer.parseInt(as.getEca());
			ec.b=Integer.parseInt(as.getEcb());
			ec.p=(Integer.parseInt(as.getEcp()));
			//判断通信双方都是存在的用户
			File obu1file=new File(obu1path);
			File obu2file=new File(obu2path);
			if (!obu1file.exists())
				throw new RuntimeException("请求通信的车辆不存在");
			if(!obu2file.exists())
				throw new RuntimeException("接受通信的车辆不存在");
			//1、USER1获取AS的公钥publickey1（KEYx1,KEYy1）、生成元P（x1,y1），通过认证获得的当前有效的psk1
			obu1=(OBU) UtilFactory.objectXmlDecoder(obu1path).get(0);
			String orginID=fromID;
			String psk1="null";
			Point publicpoint1=new Point(obu1.getAspublickeyx(), obu1.getAspublickeyy());
			Point p1=new Point(obu1.getAspx(),obu1.getAspy());
			psk1=obu1.getObupsk();
			psk1=psk1.substring(psk1.lastIndexOf("0")+1);
			if (psk1.equals("null")){
				//该用户是非认证的车辆，不能进行通信
				throw new RuntimeException("未认证不能进行通信");
			}
			System.out.println("请求通信的车辆存储的AS服务商的公钥为:"+publicpoint1);
			System.out.println("请求通信的车辆存储的AS服务商的生成元为:"+p1);
			System.out.println("请求通信的车辆当前的PSK为:"+psk1);
			//2、产生一个随机数r1
			//String r1=""+new Random().nextInt(1000);
			String r1="6";
			int r1num=6;
			System.out.println("请求通信的车辆产生的随机数为:"+r1);
			
			//3、将r1与publickey1乘积的hash值与ID1进行异或得到AID1
			Point temp1=ec.dianchen(r1num, publicpoint1);
			System.out.println("r1和公钥的点乘运算得到的点为:"+temp1);
			System.out.println("结果点横坐标与纵坐标连接的hash值为:"+UtilFactory.SHA512(temp1.getX()+temp1.getY()));
			String AID1=UtilFactory.HexXor(UtilFactory.SHA512(temp1.getX()+temp1.getY()), orginID);
			System.out.println("请求通信车辆计算出来的AIDi为:"+AID1);
			//4、将r1与P（x1，y1）相乘得到点T(Tx1,Ty1)
			System.out.println("p1"+p1);
			Point T=ec.dianchen(r1num, p1);
			System.out.println("请求通信车辆计算出来的T值为:"+T);
			
			
			//5、将psk1与P（x1,y1）相乘得到的点+T得到点u1(u1x1,u1y1)
			Point u1=ec.addtwoPoint(ec.dianchen(Integer.parseInt(psk1), p1), T);
			System.out.println("请求通信车辆计算出来的ui值为:"+u1);
			
			//6、将T1、u1、AID1的连接进行hash运算得到M1
			String M1=UtilFactory.SHA512(T.getX()+T.getY()+u1.getX()+u1.getY()+AID1);
			System.out.println("请求通信车辆计算出来的M1:"+M1);
			//USER1将AID1，u1,M1发送给USER2
			System.out.println("ID为:"+fromID+"的车辆将生成的信息发送给接收通信的车辆");
			System.out.println("接受通信车辆收到信息，进行验证");
			//7、USER2获取自己的ID2、AS的公钥publickey2(keyx2,keyy2)、生成元P（x2,y2）,通过认证获得的当前有效的psk2（当前所有用户为同一个值）
			obu2=(OBU) UtilFactory.objectXmlDecoder(obu2path).get(0);
			String psk2="null";
			Point publickey2=new Point(obu2.getAspublickeyx(),obu2.getAspublickeyy());
			Point p2=new Point(obu2.getAspx(),obu2.getAspy());
			psk2=obu2.getObupsk();
			psk2=psk2.substring(psk2.lastIndexOf("0")+1);
			if (psk2.equals("null")){
				//该车辆为非法车辆，结束通信
				throw new RuntimeException("车辆B非法，结束通信");
			}
			System.out.println("接受通信车辆存储的AS服务商的公钥为:"+publickey2);
			System.out.println("接受通信车辆存储的AS服务商的生成元为:"+p2);
			System.out.println("接受通信车辆通过认证得到的PSK为:"+psk2);
			
			// 8、将u1-psk2与P（x2,y2）相乘的值得到新的点T2(Tx2,Ty2)
			Point tp=ec.dianchen(Integer.parseInt(psk2), p2);
			System.out.println("psk与生成元的点乘得到的点为:"+tp);
			//得到点的逆元
			tp.setY("-"+tp.getY());
			Point T2=ec.addtwoPoint(u1, tp);
			System.out.println("计算得到的T值为:"+T2);
			
			//9、将T2、u1、AID1的连接进行hash运算得到值与M1对比，相同则继续通信，否则结束通信
			String M1get=UtilFactory.SHA512(T2.getX()+T2.getY()+u1.getX()+u1.getY()+AID1);
			System.out.println("接受通信车辆计算出来的M1信息为:"+M1get);
			if (!M1get.equals(M1)){
				throw new RuntimeException("M1不一致，通信非法");
			}
			//10、产生一个随机数r2，将r2与publickey2相乘再进行hash运算的值与ID2进行异或运算得到AID2
			String r2="7";
			int r2num=7;
			System.out.println("接受通信车辆产生的随机数为:"+r2);
			Point tp2=ec.dianchen(r2num, publickey2);
			System.out.println("随机数和公钥进行点乘运算得到的点为:"+tp2);
			String AID2=UtilFactory.HexXor(toID, UtilFactory.SHA512(tp2.getX()+tp2.getY()));
			System.out.println("接受通信车辆计算出的AIDj为:"+AID2);
			
			//11、r2与P（x2,y2）相乘得到新的点R（Rx，Ry）
			Point R=ec.dianchen(r2num, p2);
			System.out.println("接受通信车辆计算出来的R点为:"+R);
			
			//12、将psk2*P（x2，y2）的值加上R（Rx，Ry）得到新的点u2(u2x1,u2y1)
			Point u2=ec.addtwoPoint(ec.dianchen(Integer.parseInt(psk2) ,p2),R);
			System.out.println("接受通信车辆计算出来的uj点为:"+u2);
			
			//13、将r2*T2(Tx2,Ty2)得到新的点S（Sx,Sy）
			Point s=ec.dianchen(r2num, T2);
			System.out.println("接受通信车辆计算出来的s:"+s);
			
			//14、将T2、R、S进行连接再进行hash运算得到K2
			String K=UtilFactory.SHA512(T2.getX()+T2.getY()+R.getX()+R.getY()+s.getX()+s.getY());
			System.out.println("接受通信车辆计算出来的k:"+K);
			//15、将AID2与K进行连接再计算hash值得到M2
			String M2=UtilFactory.SHA512(AID2+K);
			System.out.println("接受通信车辆计算出来的M2:"+M2);
			System.out.println("接受通信车辆将计算出来的信息发送给请求通信车辆");
			
			/**
			 * USER2将AID2，u2,M2发送给USER1
			 */
			System.out.println("请求通信车辆接收到对方发送过来的信息，开始进行处理");
			//16、u2-psk1*P(x1,y1)得到R1(R1x,R1y)
			Point tp3=ec.dianchen(Integer.parseInt(psk1), p1);
			System.out.println("请求通信车辆用自己拥有的PSK与AS生成元进行点乘得到的点为:"+tp3);
			//得到点的逆元
			tp3.setY("-"+tp3.getY());
			Point R1=ec.addtwoPoint(u2, tp3);
			System.out.println("请求通信车辆计算出来的R值为:"+R1);
			//17、r1*R1得到S1(S1x,S1y)
			Point s1=ec.dianchen(r1num, R1);
			System.out.println("请求通信车辆计算出来的S的值为:"+s1);
			//18、计算k1=hash(T||R1||s1)
			String k1=UtilFactory.SHA512(T.getX()+T.getY()+R1.getX()+R1.getY()+s1.getX()+s1.getY());
			System.out.println("请求通信车辆计算出来的K值为:"+k1);
			//19、验证M2？=hash(AID2||k1)
			String M2get=UtilFactory.SHA512(AID2+k1);
			System.out.println("请求通信车辆计算出来的M2值为:"+M2get);
			if (!M2get.equals(M2)){
				throw new RuntimeException("发送方收到的M2不一致，结束通信");
			}
			
			//20、计算M3=hash(u1||k1)
			String M3=UtilFactory.SHA512(u2.getX()+u2.getY()+k1);
			System.out.println("请求通信车辆计算出来的M3值为:"+M3);
			System.out.println("请求通信车辆将M3发送给接受通信车辆");
			//USER1将M3发送给USER2
			//21、验证M3？=hash(u2||K2)
			System.out.println("接受通信车辆接受到M3，验证一致性");
			String M3get=UtilFactory.SHA512(u2.getX()+u2.getY()+K);
			if (!M3get.equals(M3)){
				System.out.println("接收方未收到正确的确认信息M3");
				throw new RuntimeException("接收方未收到正确的确认信息M3");
			}
			System.out.println("通信互相认证身份结束，双方获取到通信密钥");
			communicationKey=K;
			
		} catch (Exception e) {
			System.out.println("通信过程异常"+e.getMessage());
		}
		 return communicationKey;
	}
	
	
	/**
	 * 举报通信过程中的恶意车辆,返回恶意车辆的ID
	 * @param AID 被举报车辆发送给举报车辆的AID信息
	 * @param ux  被举报车辆发送给举报车辆的u的x坐标
	 * @param uy  被举报车辆发送给举报车辆的u的y坐标
	 * @return 被举报车辆的登陆ID
	 */
	public static String report(String fromID){
		System.out.println("ID为:"+fromID+"的车辆在通信过程中被举报");
		EC ec=new EC();
		ASserver as=new ASserver();
		as.setEca("1");
		as.setEcb("1");
		as.setEcp("23");
		as.setEcpx("1");
		as.setEcpy("1");
		as.setPrivatekey("7");
		as.setPubkeyx("7");
		as.setPublickeyy("2");
		String aspath=path+"0000000000.xml";
		String psk="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011";
		Point p=new Point();
		String prikey="null";
		String evilID="null";
		
		int keyx=0,keyy=0,x=0,Px=0,Py=0;
		//1获取AS服务商的公钥Ppublickey（keyx,keyy）,秘钥（x），生成元P（Px,Py）
		try {
			//as=(ASserver) UtilFactory.objectXmlDecoder("ObjectXml/0000000000.xml").get(0);
			ec.setA(Integer.parseInt(as.getEca()));
			ec.setP(Integer.parseInt(as.getEcp()));
			p.setX(as.getEcpx());
			p.setY(as.getEcpy());
			prikey=as.getPrivatekey();
			Point publicpoint1=new Point(as.getPubkeyx(),as.getPublickeyy());
			/**
			 * 模拟ID为fromID的用户与另外车辆进行通信时被举报了
			 */
			System.out.println("生成该车辆在请求通信过程中产生的AID值和u值");
			int r1num=7;
			Point temp1=ec.dianchen(r1num, publicpoint1);
			System.out.println("产生的随机数和AS公钥的点乘得到的点为:"+temp1);
			System.out.println("结果点的X坐标和Y坐标连接的hash值为:"+UtilFactory.SHA512(temp1.getX()+temp1.getY()));
			String AID=UtilFactory.HexXor(UtilFactory.SHA512(temp1.getX()+temp1.getY()), fromID);
			System.out.println("计算得到的AIDi为:"+AID);
			//4、将r1与P（x1，y1）相乘得到点T(Tx1,Ty1)
			Point T=ec.dianchen(r1num, p);
			System.out.println("计算得到的T点为:"+T);
			
			
			//5、将psk1与P（x1,y1）相乘得到的点+T得到点u1(u1x1,u1y1)
			Point u=ec.addtwoPoint(ec.dianchen(Integer.parseInt(psk), p), T);
			System.out.println("计算得到的ui为:"+u);
			System.out.println("AS服务商接收到举报的AID和u信息，开始进行处理");
			//4、计算rP=u(ux,uy)-psk*P
			Point temp=ec.dianchen(Integer.parseInt(psk), p);
			System.out.println("将当前有效的PSK和生成元进行点乘运算得到的点为:"+temp);
			temp.setY("-"+temp.getY());
			Point rp=ec.addtwoPoint(u, temp);
			System.out.println("计算出来的ri和生成元进行点乘运算得到的点为:"+rp);
			Point xrp=ec.dianchen(Integer.parseInt(prikey), rp);
			System.out.println("计算出来的ri和公钥进行点乘运算得到的点为:");
			//5、计算ID=AID异或hash(x*rp)
			String ID=UtilFactory.HexXor(AID, UtilFactory.SHA512(xrp.getX()+xrp.getY()));
			ID=ID.substring(ID.lastIndexOf("0")+1,ID.length());
			System.out.println("计算出来被举报的车辆ID为:"+ID);
			evilID=ID;
		} catch (Exception e) {
			System.out.println("获取服务商信息异常"+e.getMessage());
		}
		
		return evilID;
	}
	
	public static int ASinit(String a,String b,String p,String px,String py,String prikey){
		System.out.println("AS服务根据提供的参数开始进行初始化");
		int returnvalue=0;
		ASserver as=new ASserver();
		as.setAsid("0000000000");
		as.setEca(a);
		as.setEcb(b);
		as.setEcp(p);
		as.setEcpx(px);
		as.setEcpy(py);
		as.setHash("SHA-512");
		as.setPrivatekey(prikey);
		String ASID=UtilFactory.ECinit(as);
		if(ASID.equals("null")){
			System.out.println("AS初始化失败");
		}else{
			//AS初始化成功，生成了公钥秘钥对以及存储了椭圆曲线的各个参数
			//生成psk集合
			System.out.println("开始生成psk集合");
			int status=UtilFactory.initPsk(10);
			if(status!=0)
				returnvalue=1;
		}
		System.out.println("AS服务商初始化完成");
		return returnvalue;
	}
	
	public static String updatePsk(String ID){
		System.out.println("ID为:"+ID+"的合法车辆请求更新PSK");
		String psk="8f4fb76a0ed98c98b7e123dbe34549bacbbb4f6b9ab1e477e39988a9c34e8e3ee6a31a4dbde3f15c5c5ae5e484dbf23f4ddd55ff9d01e49607567fd206e278fb";
		String newPsk="null";
		String msg="abcdadab124154";
		System.out.println("MSG信息为:"+msg);
		String pskold="";
		OBU obu=new OBU();
		String obupath=path+ID+".xml";
		try {
			File obufile=new File(obupath);
			if (!obufile.exists())
				throw new RuntimeException("更新PSK过程异常");
			//验证此用户是否存在，不存在则结束更新
			obu=(OBU)UtilFactory.objectXmlDecoder(obupath).get(0);
			pskold=obu.getObupsk();
			if (pskold.equals("null"))
				throw new RuntimeException("该用户未进行过认证，请重新认证");
			
			String N5=""+new Random().nextInt(10);
			System.out.println("用户端产生的随机数N5:"+N5);
			String M1=UtilFactory.HexXor(pskold, N5);
			System.out.println("用户端计算出来的M1为:"+M1);
			String M2=UtilFactory.HexXor(pskold, msg);
			System.out.println("用户端计算出来的M2为:"+M2);
			String M3=UtilFactory.SHA512(N5+msg);
			System.out.println("用户端计算出来的M3为:"+M3);
			System.out.println("用户端将M1，M2，M3发送给LE，请求更新PSK");
			System.out.println("LE接受到用户端发来的消息，开始处理");
			String N5get=UtilFactory.HexXor(M1, pskold);
			N5get=N5get.substring(N5get.lastIndexOf("0")+1);
			System.out.println("LE计算出来的随机数N5为:"+N5get);
			String msgget=UtilFactory.HexXor(pskold,M2);
			msgget=msgget.substring(msgget.lastIndexOf("0")+1);
			System.out.println("LE计算出来的MSG为:"+msgget);
			
			String M3get=UtilFactory.SHA512(N5get+msgget);
			System.out.println("LE计算出来的M3为:"+M3get);
			if (!M3get.equals(M3))
				throw new RuntimeException("M3信息不匹配");
			
			String N6=""+new Random().nextInt(10);
			System.out.println("LE产生的随机数为:"+N6);
			String M4=UtilFactory.HexXor(N6, UtilFactory.SHA512(N5get));
			System.out.println("LE计算出来的M4值为:"+M4);
			String M5=UtilFactory.HexXor(psk, N6);
			System.out.println("LE计算出来的M5值为:"+M5);
			String M6=UtilFactory.SHA512(N6+psk);
			System.out.println("LE计算出来的M6值为:"+M6);
			String SKij=UtilFactory.SHA512(N5+N6+psk);
			System.out.println("LE计算出来的SKij值为:"+SKij);
			System.out.println("LE将M4，M5，M6发送给用户");
			System.out.println("用户端接收到LE发送来的信息，进行处理");
			String N6get=UtilFactory.HexXor(M4, UtilFactory.SHA512(N5));
			N6get=N6get.substring(N6get.lastIndexOf("0")+1);
			System.out.println("用户端计算出来的N6为:"+N6get);
			String pskget=UtilFactory.HexXor(M5, N6get);
			System.out.println("用户端计算出来的PSK为:"+pskget);
			String M6get=UtilFactory.SHA512(N6get+pskget);
			System.out.println("用户端计算出来的M6:"+M6get);
			if (!M6get.equals(M6))
				throw new RuntimeException("M6信息不匹配");
			
			String SKijget=UtilFactory.SHA512(N5+N6get+pskget);
			System.out.println("用户端计算出来的SKij为:"+SKijget);
			if (!SKijget.equals(SKij))
				throw new RuntimeException("SKij信息不成立");
			
			String reply=UtilFactory.HexXor(SKijget, UtilFactory.SHA512(N6get));
			System.out.println("用户端生成的告知LE的信息为:"+reply);
			System.out.println("用户端将告知信息发送给LE");
			System.out.println("LE接收到用户发送过来的告知信息，进行验证");
			String replyget=UtilFactory.HexXor(SKij, UtilFactory.SHA512(N6));
			System.out.println("LE计算出来的告知信息为:"+replyget);
			
			if (!replyget.equals(reply))
				throw new RuntimeException("LE未收到正确的回复信息");
			newPsk=pskget;
			System.out.println("PSK更新完成，用户端将获得最新的PSK");
		} catch (Exception e) {
			System.out.println("更新psk失败:"+e.getMessage());
		}
		
		return newPsk;
	}

}
